/**
  *****************************************************************************
  * @file 
  * @brief 
  * @author luffy
  * @version V1.0.0
  * @date 2022/12/02
  *****************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "SC16IS752.h"
#include "drv_f4_gpioexit.h"

/* Private defines -----------------------------------------------------------*/

/* Private Struct  -----------------------------------------------------------*/

/* Private enum    -----------------------------------------------------------*/

/* Private Variable  ---------------------------------------------------------*/
//Pointer

//Array

//Const
uint8_t Sc16is752_FifoAvailableData (dev_sc16is752_t *this, uint8_t channel);

/* Private function prototypes -----------------------------------------------*/

/*****************************************************************************
* @brief 读SC16IS7xx内部寄存器
* ex:
* @par
** Input parameters:        addr        寄存器
**                          channel     0:通道A, 1:通道B 
**                          len         要读出数据的字节个数
** Output parameters:       buf         接收数据缓冲区
* @retval 
*****************************************************************************/
int sc16is7xxRegRead (dev_sc16is752_t *this, 
						  uint8_t   addr, 
                          uint8_t   channel, 
                          uint8_t  *buf,
                          uint8_t   len)
{
	uint8_t regAddr;        

    if (!len) 
	{
        return -1;
    }
	
    regAddr = (addr << 3) | (channel << 1);  //手册Table 33                                      
    
	// 错误时重运行，中断或线程打断操作时可以进行重发
    //while(this->private.i2c.Read(&this->private.i2c, SC16IS7XX_ADDR, regAddr, buf, len) < 0){
	while(this->private.i2c.Read(&this->private.i2c, SC16IS7XX_ADDR, regAddr, buf, len) < 0){
        ;
    }
	             
    return 0;
}

/*****************************************************************************
* @brief 写SC16IS7xx内部寄存器
* ex:
* @par
** Input parameters:        ucReg       寄存器
**                          ucChannel   0:通道A, 1:通道B  
**                          pucDat      发送数据缓冲区
**                          ucNum       要写入数据的字节个数
* @retval 
*****************************************************************************/
int sc16is7xxRegWrite (dev_sc16is752_t *this, 
						   uint8_t   addr,
                           uint8_t   channel,
                           uint8_t  *buf,
                           uint8_t   len)
{
	uint8_t regAddr;

    if (!len) {
        return -1;
    }
	
    regAddr = (addr << 3) | (channel << 1);
	
	// 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Write(&this->private.i2c, SC16IS7XX_ADDR, regAddr, buf, len) < 0){
        ;
    }                                            
                   
    return 0;
}

/*****************************************************************************
* @brief 接收数据
* ex:
* @par
** Input parameters:        channel     0:通道A, 1:通道B 
**                          len         要读出数据的字节个数
** Output parameters:       buf         接收数据缓冲区
* @retval 
*****************************************************************************/
uint8_t iir[64] = {0};
uint8_t iir2[64] = {0};

uint8_t iir_st = 0;
uint8_t aviable = 0;
uint8_t rx_buf[64];
uint8_t* p_rxbuf = rx_buf;
void Sc16is752_DataRead (dev_sc16is752_t *this, uint8_t channel, uint8_t *buff, uint8_t len)
{
	#if 0
	//uint8_t iir = 0;
	
	sc16is7xxRegRead(this, SC16IS7XX_TXLVL, SC16IS7XX_CHA, &iir[0], 1); /* 使能RX TX FIFO */
	
	
	
	//sc16is7xxRegRead(this, SC16IS7XX_RXLVL, SC16IS7XX_CHA, &iir[1], 1); /* 使能RX TX FIFO */
	
	sc16is7xxRegRead(this, SC16IS7XX_IIR, SC16IS7XX_CHA, &iir_st, 1); /* 接收数据 */

		// IIR[5:1] 5-bit encoded interrupt
//	switch(iir & 0x3E) {
//		case RHR: DataReady = 1; break;
//		default : break;

//	}
	
	aviable = Sc16is752_FifoAvailableData(this, SC16IS7XX_CHA);
	
	//SoftDelay_us(10);   
	
  sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, p_rxbuf++, 1); /* 接收数据 */
	
	//sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, buff, 1); /* 接收数据 */
	
		
	//uint8_t ucTmp = 0x02;
	//sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* clears the contents of the transmit FIFO */
	#else
	sc16is7xxRegRead(this, SC16IS7XX_IIR, SC16IS7XX_CHA, &iir_st, 1); /* 读取中断状态寄存器 */
	iir_st &= 0x3F;
	switch(iir_st){
		case TIME_OUT:
		case RHR: sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, p_rxbuf++, 1); /* 接收数据 */
			break;
		case THR:
			break;
		default:
			break;
	}
	#endif
}

/*****************************************************************************
* @brief 接收数据
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
void Sc16is752_DataWrite (dev_sc16is752_t *this, uint8_t channel, uint8_t *buff, uint8_t len)
{
	
	uint8_t ucTmp = 0x04;
	sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* clears the contents of the transmit FIFO */
	
  sc16is7xxRegWrite(this, SC16IS7XX_THR, channel, buff, len); /* 发送数据 */
}

/*****************************************************************************
* @brief Sc16is752_FifoEnable
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
void Sc16is752_FifoEnable (dev_sc16is752_t *this, uint8_t channel, uint8_t enable)
{
	uint8_t ucTmp = 0x00;
	
	sc16is7xxRegRead(this, SC16IS7XX_FCR, channel, &ucTmp, 1); 
	
	if (enable == 0){
		ucTmp &= 0xFE;
	} else {
		ucTmp |= 0x01;
	}

	sc16is7xxRegWrite(this, SC16IS7XX_FCR, channel, &ucTmp, 1); 
}

/*****************************************************************************
* @brief Sc16is752_FifoReset
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
void Sc16is752_FifoReset (dev_sc16is752_t *this, uint8_t channel, uint8_t rx_fifo)
{
	uint8_t ucTmp = 0x00;
	
	sc16is7xxRegRead(this, SC16IS7XX_FCR, channel, &ucTmp, 1); 
	
	if (rx_fifo == 0){
		ucTmp |= 0x04;
	} else {
		ucTmp |= 0x02;
	}

	sc16is7xxRegWrite(this, SC16IS7XX_FCR, channel, &ucTmp, 1); 
}

/*****************************************************************************
* @brief Sc16is752_FifoReset
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
void Sc16is752_FifoSetTriggerLevel (dev_sc16is752_t *this, uint8_t channel, uint8_t rx_fifo, uint8_t length)
{
	uint8_t ucTmp = 0x00;
	uint8_t ucTmpReg = 0x00;
	
	sc16is7xxRegRead(this, SC16IS7XX_MCR, channel, &ucTmp, 1); 
	ucTmp |= 0x04;
	sc16is7xxRegWrite(this, SC16IS7XX_MCR, channel, &ucTmp, 1);  //SET MCR[2] to '1' to use TLR register or trigger level control in FCR register
	
	sc16is7xxRegRead(this, SC16IS7XX_EFR, channel, &ucTmpReg, 1); 
	ucTmp = ucTmpReg|0x10;
	sc16is7xxRegWrite(this, SC16IS7XX_EFR, channel, &ucTmp, 1); //set ERF[4] to '1' to use the  enhanced features
	
	if (rx_fifo == 1){
		ucTmp = length<<4;
		sc16is7xxRegWrite(this, SC16IS7XX_TLR, channel, &ucTmp, 1);  //Tx FIFO trigger level setting
	} else {
		ucTmp = length;
		sc16is7xxRegWrite(this, SC16IS7XX_TLR, channel, &ucTmp, 1);  //Rx FIFO Trigger level setting
	}
	
	sc16is7xxRegWrite(this, SC16IS7XX_EFR, channel, &ucTmpReg, 1);  //restore EFR register
}

/*****************************************************************************
* @brief Sc16is752_FifoAvailableData
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
uint8_t Sc16is752_FifoAvailableData (dev_sc16is752_t *this, uint8_t channel)
{
	uint8_t ucTmp = 0x00;
	
	sc16is7xxRegRead(this, SC16IS7XX_RXLVL, channel, &ucTmp, 1); 
	
	return ucTmp;
}

/*****************************************************************************
* @brief Sc16is752_FifoAvailableSpace
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
uint8_t Sc16is752_FifoAvailableSpace (dev_sc16is752_t *this, uint8_t channel)
{
	uint8_t ucTmp = 0x00;
	
	sc16is7xxRegRead(this, SC16IS7XX_TXLVL, channel, &ucTmp, 1); 
	
	return ucTmp;
}

/*****************************************************************************
* @brief Sc16is752_FifoControl
* ex:
* @par
** Input parameters:        channel   0:通道A, 1:通道B  
**                          buff      发送数据缓冲区
**                          len       要写入数据的字节个数
* @retval 
*****************************************************************************/
void Sc16is752_FifoControl (dev_sc16is752_t *this, uint8_t channel, uint8_t fifo)
{
	uint8_t ucTmp = fifo;
	
	sc16is7xxRegWrite(this, SC16IS7XX_FCR, channel, &ucTmp, 1); 
}



/***********************************************************************************
 * @brief  SC16IS7xx初始化，默认为无校验，1位停止位，数据位长度8
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
uint8_t tlr_st = 0;
uint8_t fcr_st = 0;
int Dev_Sc16is752_Init(dev_sc16is752_t *this) 
{
	uint8_t ucTmp = 0x80;
	
	// I2C对象初始化
	this->private.i2c.PIN_SDA = this->PIN_SDA;
	this->private.i2c.PIN_SCL = this->PIN_SCL;
	this->private.i2c.SPEED = I2C_SPEED_HIGH; //I2C_SPEED_SLOW;
	this->private.i2c.WIDTH = I2C_WIDTH_BYTE; // I2C_WIDTH_HALFWORLD;
	this->private.i2c.ACK_TIMEOUT = I2C_TIMEOUT_STOP;
	this->private.i2c.ACK_WAIT_US = 10;
	if (Drv_I2c_Init(&this->private.i2c) < 0)
	{
		return -1;
	}

	// IRQ io config
	if (this->PIN_IRQ != NULL)
	{
//		this->private.irq.PIN = this->PIN_IRQ;
//		this->private.irq.MODE = INPUT_DOWN;
//		this->private.irq.INIT_LEVEL = HIGHT_LEVEL; // low level inhibit write to Status Register when WPEN is 1
//		if (Drv_Gpio_Init(&this->private.irq) < 0)
//		{
//			return -1;
//		}
		
		
		
		this->private.irq.PIN 			    = this->PIN_IRQ;
        this->private.irq.MODE 			    = INPUT_UP;
        this->private.irq.trigger           = falling;       //下降沿触发
        this->private.irq.PreempPriority    = 3;             //中断优先级
        this->private.irq.callback          = this->Int_Callback;
		
        if(Drv_GpioExit_Init(&this->private.irq) < 0){
            return -1;
        }
		
		GpioExit_Set(&this->private.irq, 1);
	}

	// 公共方法赋值
	this->Write = Sc16is752_DataWrite;
	this->Read = Sc16is752_DataRead;
	
	uint32_t bps = this->BaudRate;
	bps = SC16IS7XX_FXTAL / bps / 16; 

	// reset device
	//ucTmp = 0x08;
	//sc16is7xxRegWrite(this, SC16IS7XX_IOCONTROL, SC16IS7XX_CHA, &ucTmp, 1); /* software reset. */
	
	//配置通道A
	ucTmp = 0x80;
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHA, &ucTmp, 1); /* LCR[7] 除数锁存使能 允许访问特殊寄存器 */
	ucTmp = 0; //(uint8_t)(bps >> 8);
	sc16is7xxRegWrite(this, SC16IS7XX_DLH, SC16IS7XX_CHA, &ucTmp, 1); /* 设置波特率 高位 */
	ucTmp = (uint8_t)bps;
	sc16is7xxRegWrite(this, SC16IS7XX_DLL, SC16IS7XX_CHA, &ucTmp, 1); /* 设置波特率 低位 */
	
	ucTmp = 0xBF;
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */

	ucTmp = 0x10;
	//sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHA, &ucTmp, 1); /* enable enhanced functions. */
	
	ucTmp = 0x03;                                               /* 8位数据 1位停止 无奇偶校验 */
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHA, &ucTmp, 1); /* 设置数据通讯格式 */
	
	//---- add fifo ctrl -------
	//ucTmp = 0x10;
	//sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHA, &ucTmp, 1); /* enable enhanced functions. */
	//sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	//ucTmp &= 0x3F;
	//sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	
	
	sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &fcr_st, 1); /* 使能RX TX FIFO */
	
	//ucTmp = 0x06;
	//sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	//--------------------------
	Sc16is752_FifoEnable (this,  SC16IS7XX_CHA, 1);
	Sc16is752_FifoSetTriggerLevel ( this,  SC16IS7XX_CHA,  1,  0x4);
	
	
	//Sc16is752_FifoControl(this,  SC16IS7XX_CHA, 0x06); /* reset fifo. */ 
	//Sc16is752_FifoControl(this,  SC16IS7XX_CHA, 0xF1);
	
//	ucTmp = 0x10;
//	sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */
	
	
//		// set RX FIFO trigger level = 16 char
//	ucTmp = 0x10;
//	sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */
//	ucTmp = 0xC3;
//	//sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
//	sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */

//	// Set trigger level register
//	ucTmp = 0x10;
//	sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */
//	ucTmp = 0x04;
//	sc16is7xxRegWrite(this, SC16IS7XX_MCR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */
//	ucTmp = 0xF0;
//	sc16is7xxRegWrite(this, SC16IS7XX_TLR, SC16IS7XX_CHA, &ucTmp, 1); /* access sepcial register. */

	// enable IO
	ucTmp = 0xFF;                                                                                                                                                                             
	sc16is7xxRegWrite(this, SC16IS7XX_IODIR, SC16IS7XX_CHA, &ucTmp, 1); 
	
	ucTmp = 0x00;                                                                                                                                                                             
	sc16is7xxRegWrite(this, SC16IS7XX_IOSTATE, SC16IS7XX_CHA, &ucTmp, 1); 

	ucTmp = 0x01;                                               /*使能 接收保存寄存器中断 接收线状态中断 */                                                                                                                                  
	sc16is7xxRegWrite(this, SC16IS7XX_IER, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX 中断 */
	
//	sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
//	ucTmp &= 0x3F;
//	sc16is7xxRegWrite(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
//	
//	
//	sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHA, &fcr_st, 1); /* 使能RX TX FIFO */
	
	sc16is7xxRegRead(this, SC16IS7XX_TLR, SC16IS7XX_CHA, &tlr_st, 1); /* 使能RX TX FIFO */

	sc16is7xxRegRead(this, SC16IS7XX_IIR, SC16IS7XX_CHA, &iir_st, 1); /* 使能RX TX FIFO */
	sc16is7xxRegRead(this, SC16IS7XX_LCR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	sc16is7xxRegRead(this, SC16IS7XX_LSR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	sc16is7xxRegRead(this, SC16IS7XX_TXLVL, SC16IS7XX_CHA, &iir2[1], 1); /* 使能RX TX FIFO */

	sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	
	//sc16is7xxRegRead(this, SC16IS7XX_IIR, SC16IS7XX_CHA, &iir_st, 1); /* 使能RX TX FIFO */
	
	for(int i=0;i<64; i++){
		sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	}
	sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHA, &ucTmp, 1); /* 使能RX TX FIFO */
	
	
	//配置通道B
	ucTmp = 0x80;
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHB, &ucTmp, 1); /* LCR[7] 除数锁存使能 允许访问特殊寄存器 */
	ucTmp = 0; //(uint8_t)(bps >> 8);
	sc16is7xxRegWrite(this, SC16IS7XX_DLH, SC16IS7XX_CHB, &ucTmp, 1); /* 设置波特率 高位 */
	ucTmp = (uint8_t)bps;
	sc16is7xxRegWrite(this, SC16IS7XX_DLL, SC16IS7XX_CHB, &ucTmp, 1); /* 设置波特率 低位 */
	
	ucTmp = 0xBF;
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHB, &ucTmp, 1); /* access sepcial register. */

	ucTmp = 0x10;
	sc16is7xxRegWrite(this, SC16IS7XX_EFR, SC16IS7XX_CHB, &ucTmp, 1); /* enable enhanced functions. */
	
	ucTmp = 0x03;                                               /* 8位数据 1位停止 无奇偶校验 */
	sc16is7xxRegWrite(this, SC16IS7XX_LCR, SC16IS7XX_CHB, &ucTmp, 1); /* 设置数据通讯格式 */
	
	//ucTmp = 0x06;
	//sc16is7xxRegRead(this, SC16IS7XX_FCR, SC16IS7XX_CHB, &ucTmp, 1); /* 使能RX TX FIFO */
	
	for(int i=0;i<64; i++){
		sc16is7xxRegRead(this, SC16IS7XX_RHR, SC16IS7XX_CHB, &ucTmp, 1); /* 使能RX TX FIFO */
	}
	
	return 0;
}

